/*
 * (c) 2007, Delsi Interactive
 * User: Usuario Deltatek
 * Date: 02/05/2007
 * Time: 08:23 p.m.
 */

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;

namespace CSE
{
	/// <summary>
	/// Description of GetClips.
	/// </summary>
	public partial class GetClips : Form
	{
		/*
		 * Constants
		 */
		public static readonly string CLIP_NAME = "clip_";
		public static readonly string WINDOW_NAME = "Working ";
		public static readonly int MAX_PROGRESS = 15;
		
		/*
		 * Variables
		 */
		private int point_count = 0;
		private int point_max = 0;
		private Point []points = null;
		
		private Rectangle r;
		
		private int ox = 0;
		private int oy = 0;
		private int lx = -1;
		private int ly = -1;
		
		private bool done = false;
		private bool cancel = false;
		private Stack<Point> stack = null;
		
		private int progress = 0;
		
		/*
		 * Constructor
		 */
		public GetClips()
		{
			MainForm.self.Enabled = false;
			r = new Rectangle(0,0,0,0);
			stack = new Stack<Point>();
			
			InitializeComponent();
			
			this.Location = new Point (MainForm.self.Location.X + (MainForm.self.Width / 2) - (this.Width / 2),
			                           MainForm.self.Location.Y + (MainForm.self.Height / 2) - (this.Height / 2));
			this.btnOk.Visible = false;
			this.btnCancel.Visible = true;
			this.prgBar.Value = 0;

			this.Show();
			this.Focus();
			
			ProcessBitmap();
		}
		
		/*
		 * For debug only
		 */
		void PicPaint(object sender, PaintEventArgs e)
		{
#if NO_DEBUG_GETCLIPS
		    Graphics g = e.Graphics;
		    
		    g.Clear(Color.Black);
		    g.DrawImage(Workspace.bitmap, 0, 0);
		    
		    Pen p = new Pen(Color.Turquoise);
		    g.DrawRectangle(p, ox-1, oy-1, 3, 3);
#endif
		}
		
        /*
         * SetTitle
         */
		private void SetTitle (int num)
		{
		    this.Text = WINDOW_NAME;
		    if (num > 0)
		    {
		        int i=0;
		        
		        for (i=0; i<MAX_PROGRESS; i++)
		        {
                    this.Text += '.';
		        }
		    }
		}
		
		/*
		 * UnloadMe
		 */
		private void UnloadMe ()
		{
			MainForm.self.Enabled = true;
			this.Dispose();
			MainForm.gc = null;
		}
		
		/*
		 * ProcessBitmap
		 */
		private void ProcessBitmap ()
		{
			Bitmap bitmap = Workspace.bitmap;
			int x=0, y=0;
        	int width = bitmap.Width;
        	int height = bitmap.Height;
        	int percent = 0;
        	int clip_num = 0;
        	Color trans = bitmap.GetPixel(0, 0);
        	
        	points = new Point[width*height];
        	point_max = width*height;
        	
        	for (y=0; y<height; y++)
        	{
        		for (x=0; x<width; x++)
        		{
        			if (bitmap.GetPixel(x, y) != trans
        		    && IsValidPoint(x, y, false))
        			{
        				ox = x;
        				oy = y;
        				r.X = x;
        				r.Y = y;
        				r.Width = 0;
        				r.Height = 0;
        				done = false;
        				
        				while (!done)
        				{
        				    r = ProcessRect(r, bitmap, trans);
        				    
        				    while (stack.Count > 0)
        				    {
        				        if (cancel)
        				        {
        				            done = true;
        				            x = width;
        				            y = height;
        				            break;
        				        }
        				        
        				        Point p = stack.Pop();
        				        ox = p.X;
        				        oy = p.Y;
        				        
        				        r = ProcessRect(r, bitmap, trans);
        				        
        				        this.picTemp.Invalidate();
			                    Application.DoEvents();
        				    }
        				}
        				
        				Utils.Trace(">> rect: " + r.ToString());
        				
        				if (r.Width > 1 && r.Height > 1)
        				{
            				MainForm.libSel = MainForm.libClipsLibrary;
        				    TreeNode nt = Workspace.NewClip(Workspace.TYPE_CLIP, (CLIP_NAME + clip_num).ToString());
        				    ((Clip)nt.Tag).r.X = r.X;
        				    ((Clip)nt.Tag).r.Y = r.Y;
        				    ((Clip)nt.Tag).r.Width = r.Width;
        				    ((Clip)nt.Tag).r.Height = r.Height;
        				    clip_num++;
        				}
        			}
        		    else
        		    {
        		        SetTitle(-1);
        		    }
        			
        			percent = int.Parse(Math.Floor((double)(((x * y) * 100) / (width * height))).ToString());
        			if (percent != 0
        			&& percent > this.prgBar.Value)
        			{
        				this.prgBar.Value = percent;
        			}
        			Application.DoEvents();
        		}
        	}
        	
        	this.btnOk.Visible = true;
        	this.btnCancel.Visible = false;
		}
		
		/*
		 * IsValidPoint
		 */
		private bool IsValidPoint (int x, int y, bool mustbe)
		{
			int i=0;
			
			for (i=0; i<point_max; i++)
			{
				if (i > point_count)
				{
					break;
				}
				
				if (points[i].X == x
				&& points[i].Y == y)
				{
					return false;
				}
			}
			
			if (!mustbe)
			{
				return true;
			}
			
			points[i] = new Point(x, y);
			point_count++;
			return true;
		}
		
		/*
		 * ProcessRect
		 */
		private Rectangle ProcessRect (Rectangle r, Bitmap bitmap, Color trans)
		{
		    /*
		     * SetTitle(progress);
		    
		    progress++;
		    if (progress > MAX_PROGRESS)
		    {
		        progress = 0;
		    }
		    */
		   
		    while (ox < r.X)
            {
                r.X--;
                r.Width++;
            }
			while (ox > r.X + r.Width)
            {
                r.Width++;
            }
			while (oy < r.Y)
            {
                r.Y--;
                r.Height++;
            }
			while (oy > r.Y + r.Height)
			{
				r.Height++;
			}
			
			if (!IsValidPoint(ox, oy, true))
			{
				int old_x = ox;
				int old_y = oy;
				int start = old_x - 1;
				bool anyvalid = false;
				
				while (bitmap.GetPixel(start, old_y) != trans)
				{
				    Application.DoEvents();
				    
				    if (IsValidPoint(start, old_y, false))
				    {
				        ox = start;
				        stack.Push(new Point(start, old_y));
				        anyvalid = true;
				        break;
				    }
				    start--;
				}
				
				start = old_x + 1;
				while (bitmap.GetPixel(start, old_y) != trans)
				{
				    Application.DoEvents();
				    
				    if (IsValidPoint(start, old_y, false))
				    {
				        ox = start;
				        stack.Push(new Point(start, old_y));
				        anyvalid = true;
				        break;
				    }
				    start++;
				}
				
				start = old_y - 1;
				while (bitmap.GetPixel(old_x, start) != trans)
				{
				    Application.DoEvents();
				    
				    if (IsValidPoint(old_x, start, false))
				    {
				        oy = start;
				        stack.Push(new Point(old_x, start));
				        anyvalid = true;
				        break;
				    }
				    start--;
				}
				
				start = old_y + 1;
				while (bitmap.GetPixel(old_x, start) != trans)
				{
				    Application.DoEvents();
				    
				    if (IsValidPoint(old_x, start, false))
				    {
				        oy = start;
				        stack.Push(new Point(old_x, start));
				        anyvalid = true;
				        break;
				    }
				    start++;
				}
				
				if (!anyvalid)
				{
				    done = true;
				}
                
				return r;
			}
			
			lx = ox;
			ly = oy;
			
			// LEFT
			if (bitmap.GetPixel(ox - 1, oy) != trans)
			{
			    if (IsValidPoint(ox - 1, oy, false))
			    {
				    ox--;
				    stack.Push(new Point(ox, oy));
			    }
			}
			
			// RIGHT
			if (bitmap.GetPixel(ox + 1, oy) != trans)
			{
				if (IsValidPoint(ox + 1, oy, false))
			    {
				    ox++;
    				stack.Push(new Point(ox, oy));
				}
			}
			
			// TOP
			if (bitmap.GetPixel(ox, oy - 1) != trans)
			{
				if (IsValidPoint(ox, oy - 1, false))
			    {
				    oy--;
    				stack.Push(new Point(ox, oy));
				}
			}
			
			// BOTTOM
			if (bitmap.GetPixel(ox, oy + 1) != trans)
			{
				if (IsValidPoint(ox, oy + 1, false))
			    {
				    oy++;
    				stack.Push(new Point(ox, oy));
				}
			}
			
			return r;
		}
		
		/*
		 * Ok
		 */
		void BtnOkClick(object sender, EventArgs e)
		{
			UnloadMe();
		}
		
		/*
		 * Cancel
		 */
		void BtnCancelClick(object sender, EventArgs e)
		{
			cancel = true;
		}
	}
}
